package nba2kmodtool.filedesc;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import nba2kmodtool.util.ByteFileReader;

/**
 * NBA2K Game Texture Importer
 * @company ZSword (C) Copyright
 * @author JemiZhuu(周士淳)
 * @category N2kTextureImporter
 * @version 1.0
 * @since 2011-11-16
 */
public class N2kTextureImporter {
	private static final boolean IS_DEBUG = BaseIffFile.IS_DEBUG;

	protected BaseIffFile iff;
	protected long fileType;
	protected File file;
	protected File cdfFile;

	protected N2kTextureImporter(BaseIffFile iff) {
		this.iff = iff;
		this.fileType = iff.fileType;
		this.file = iff.file;
		this.cdfFile = iff.cdfFile;
	}

	/**
	 * Import Texture File into IFF
	 * @param impfile
	 * @param target
	 * @throws IOException
	 */
	public void importTextureFile(File impfile, N2kTextureFile target) throws IOException {
		ByteFileReader in = new ByteFileReader(impfile, "r");
		ByteFileReader out = null;
		if (fileType == 0xFF3BEF94L) {
			out = new ByteFileReader(file, "rw");
		} else if (fileType == 0xF0985030L) {
			out = new ByteFileReader(cdfFile, "rw");
		}
		if ("BMP".equals(target.pixelFormat)) {
			this.importBMPTexture(in, out, target);
		} else {
			this.importDDSTexture(in, out, target);
		}
		in.close();
		out.close();
	}

	/**
	 * Import BMP Texture data
	 * @param in
	 * @param out
	 * @param target
	 * @throws IOException
	 */
	private void importBMPTexture(ByteFileReader in, ByteFileReader out, N2kTextureFile target) throws IOException {
		int bmpHeaderSize = 0x36;
		int size = target.width * target.height * 4;
		in.seek(bmpHeaderSize);
		if (size > in.length() - bmpHeaderSize) {
			size = (int) (in.length() - bmpHeaderSize);
		}
		ByteBuffer buffer0 = ByteBuffer.allocate(size);
		in.read(buffer0.array());
		if (target.indexType <= 0) {
			out.seek(target.dataStart);
			IntBuffer buffer = buffer0.asIntBuffer();
			for (int i = 0; i < size / 4; i++) {
				buffer.position(buffer.capacity() - i - 1);
				out.writeInt(buffer.get());
			}
		} else {
			IffBlockIndex index = target.index;
			int count = index.getIndexCount();
			int witeCount = 0;
			long restCount = size;
			for (int i = count - 1; i >= 0; i--) {
				long addr = index.getAddr(i);
				long chunkSize = index.getSize(i);
				chunkSize = (chunkSize > restCount) ? restCount : chunkSize;
				out.seek(addr);
				if (IS_DEBUG) {
					System.out.printf("BMP: data-%X-%X\n", addr, chunkSize);
				}
				out.write(buffer0.array(), witeCount, (int) chunkSize);
				witeCount += chunkSize;
				restCount -= chunkSize;
			}
		}
	}

	/**
	 * Import DDS Texture data
	 * @param in
	 * @param out
	 * @param target
	 * @throws IOException
	 */
	private void importDDSTexture(ByteFileReader in, ByteFileReader out, N2kTextureFile target) throws IOException {
		int ddsHeaderSize = 0x80;
		int size = (int) target.dataSize;
		in.seek(ddsHeaderSize);
		if (size > in.length() - ddsHeaderSize) {
			size = (int) (in.length() - ddsHeaderSize);
		}
		ByteBuffer buffer = ByteBuffer.allocate(size);
		in.read(buffer.array());
		if (target.indexType <= 0) {
			out.seek(target.dataStart);
			out.write(buffer.array());
		} else {
			IffBlockIndex index = target.index;
			int count = index.getIndexCount();
			int witeCount = 0;
			long restCount = size;
			for (int i = count - 1; i >= 0; i--) {
				long addr = index.getAddr(i);
				long chunkSize = index.getSize(i);
				chunkSize = (chunkSize > restCount) ? restCount : chunkSize;
				out.seek(addr);
				if (IS_DEBUG) {
					System.out.printf("DDS: data-%X-%X\n", addr, chunkSize);
				}
				out.write(buffer.array(), witeCount, (int) chunkSize);
				witeCount += chunkSize;
				restCount -= chunkSize;
			}
		}
	}

}
